home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / ODF / OS / FWMenu / FWPullDM.cpp < prev    next >
Encoding:
Text File  |  1996-09-17  |  23.2 KB  |  737 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWPullDM.cpp
  4. //    Release Version:    $ ODF 2 $
  5. //
  6. //    Copyright:            (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWOS.hpp"
  11.  
  12. #ifndef FWPULLDM_H
  13. #include "FWPullDM.h"
  14. #endif
  15.  
  16. #ifndef FWMNUBAR_H
  17. #include "FWMnuBar.h"
  18. #endif
  19.  
  20. #ifndef FWRESTYP_H
  21. #include "FWResTyp.h"
  22. #endif
  23.  
  24. #ifndef FWACQUIR_H
  25. #include "FWAcquir.h"
  26. #endif
  27.  
  28. // ----- Foundation Includes -----
  29.  
  30. #ifndef FWSTREAM_H
  31. #include "FWStream.h"
  32. #endif
  33.  
  34. #ifndef FWSTRING_H
  35. #include "FWString.h"
  36. #endif
  37.  
  38. //========================================================================================
  39. // File scope definitions
  40. //========================================================================================
  41.  
  42. #ifdef FW_BUILD_MAC
  43. #pragma segment fwmenu
  44. #endif
  45.  
  46. #define FW_kUnattachedMenuID    255
  47.  
  48. //========================================================================================
  49. //    Template Instantiations
  50. //========================================================================================
  51.  
  52. FW_DEFINE_AUTO_TEMPLATE(FW_TOrderedCollectionIterator, FW_CPullDownMenu)
  53. FW_DEFINE_AUTO_TEMPLATE(FW_TOrderedCollection, FW_CPullDownMenu)
  54.  
  55. #ifdef FW_USE_TEMPLATE_PRAGMAS
  56.  
  57. #pragma template_access public
  58. #pragma template FW_TOrderedCollection<FW_CPullDownMenu>
  59. #pragma template FW_TOrderedCollectionIterator<FW_CPullDownMenu>
  60.  
  61. #endif
  62.  
  63. //========================================================================================
  64. //    class FW_CPullDownMenu
  65. //========================================================================================
  66.  
  67. FW_DEFINE_CLASS_M0(FW_CPullDownMenu)
  68.  
  69. // This class is archivable, but we provide the archiving implementation in a separate
  70. // translation unit in order to enable deadstripping of the archiving-related code
  71. // in parts that do not use archiving with this class.
  72.  
  73. //----------------------------------------------------------------------------------------
  74. //    FW_CPullDownMenu::FW_CPullDownMenu
  75. //----------------------------------------------------------------------------------------
  76.  
  77. FW_CPullDownMenu::FW_CPullDownMenu(Environment* ev) :
  78.     fMenuID(FW_kUnattachedMenuID)
  79. {
  80.     FW_CString32 menuTitle(" ");
  81.     this->PrivInitialize(ev, menuTitle);
  82. }
  83.  
  84. //----------------------------------------------------------------------------------------
  85. //    FW_CPullDownMenu::FW_CPullDownMenu
  86. //----------------------------------------------------------------------------------------
  87.  
  88. FW_CPullDownMenu::FW_CPullDownMenu(Environment* ev, const FW_CString& menuTitle) :
  89.     fMenuID(FW_kUnattachedMenuID)
  90. {
  91.     this->PrivInitialize(ev, menuTitle);
  92. }
  93.  
  94. //----------------------------------------------------------------------------------------
  95. //    FW_CPullDownMenu::FW_CPullDownMenu
  96. //----------------------------------------------------------------------------------------
  97.  
  98. FW_CPullDownMenu::FW_CPullDownMenu(Environment* ev,
  99.                                    FW_PResourceFile &resFile,
  100.                                    FW_ResourceID resourceID,
  101.                                    unsigned long stringID) :
  102.     fMenuID(FW_kUnattachedMenuID)
  103. {
  104.     FW_CString32 menuTitle;
  105.     ::FW_LoadStringByID(ev, resFile, resourceID, FW_kMultiStringRes, stringID, menuTitle);
  106.     this->PrivInitialize(ev, menuTitle);
  107. }
  108.  
  109. //----------------------------------------------------------------------------------------
  110. //    FW_CPullDownMenu::FW_CPullDownMenu
  111. //----------------------------------------------------------------------------------------
  112.  
  113. FW_CPullDownMenu::FW_CPullDownMenu(Environment* ev, FW_CReadableStream& stream) :
  114.     fMenuID(FW_kUnattachedMenuID)
  115. {
  116.     FW_CString menuTitle;
  117.     stream >> menuTitle;
  118.  
  119.     this->PrivInitialize(ev, menuTitle);
  120.     
  121.     // ----- Read every items -----
  122.     short count;
  123.     stream >> count;
  124.     
  125.     FW_ASSERT(count>=0 && count <1000);    // just a sanity check
  126.     
  127.     for (short i = 0; i < count; i++)
  128.     {
  129.         FW_CMenuItem* menuItem;
  130.         FW_READ_DYNAMIC_OBJECT(stream, &menuItem, FW_CMenuItem);
  131.         AdoptMenuItemLast(ev, menuItem);
  132.     }
  133. }
  134.  
  135. //----------------------------------------------------------------------------------------
  136. //    FW_CPullDownMenu::PrivInitialize
  137. //----------------------------------------------------------------------------------------
  138.  
  139. void FW_CPullDownMenu::PrivInitialize(Environment* ev, const FW_CString& menuTitle)
  140. {
  141. FW_UNUSED(ev);
  142.     fMenuBar = NULL;
  143.     fParentMenuItem = NULL;
  144.     
  145.     fItems = FW_NEW(FW_TOrderedCollection<FW_CMenuItem>, ());
  146.     
  147. #ifdef FW_BUILD_MAC
  148.     Str255 str;
  149.     menuTitle.ExportPascal(str);
  150.     fPlatformMenu = ::NewMenu(fMenuID, str);
  151. #endif
  152.  
  153. #ifdef FW_BUILD_WIN
  154.     fPlatformMenu.menu = ::CreatePopupMenu();
  155.     menuTitle.ExportCString(fPlatformMenu.strMenu);
  156. #endif
  157. }
  158.  
  159. //----------------------------------------------------------------------------------------
  160. //    FW_CPullDownMenu::~FW_CPullDownMenu
  161. //----------------------------------------------------------------------------------------
  162.  
  163. FW_CPullDownMenu::~FW_CPullDownMenu()
  164. {
  165.     if (fItems)
  166.     {
  167.         FW_CMenuItem* item;
  168.         while ((item = fItems->First()) != NULL)
  169.         {
  170.             fItems->Remove(item);
  171.             delete item;
  172.         }        
  173.         
  174.         delete fItems;
  175.         fItems = NULL;
  176.     }
  177.  
  178. #ifdef FW_BUILD_MAC
  179.     if (fPlatformMenu)
  180.     {
  181.         ::DisposeMenu(fPlatformMenu);
  182.         fPlatformMenu = NULL;
  183.     }
  184. #endif
  185.  
  186. #ifdef FW_BUILD_WIN
  187.     if (fPlatformMenu.menu) 
  188.     {
  189.         ::DestroyMenu(fPlatformMenu.menu);
  190.         fPlatformMenu.menu = NULL;
  191.     }    
  192. #endif
  193. }
  194.  
  195. //----------------------------------------------------------------------------------------
  196. //    FW_CPullDownMenu::AppendTextItem
  197. //----------------------------------------------------------------------------------------
  198.  
  199. void FW_CPullDownMenu::AppendTextItem(Environment* ev,
  200.                                       const FW_CString& text,
  201.                                       ODCommandID commandID,
  202.                                       FW_MenuKey menuKey)
  203. {
  204.     short index = CountItems(ev) + 1;
  205.     FW_CMenuItem* menuItem = FW_NEW(FW_CTextItem, (ev, this, index, text, commandID, menuKey));
  206.     this->AdoptMenuItemLast(ev, menuItem);
  207. }
  208.  
  209. //----------------------------------------------------------------------------------------
  210. //    FW_CPullDownMenu::InsertTextItem
  211. //----------------------------------------------------------------------------------------
  212.  
  213. void FW_CPullDownMenu::InsertTextItem(Environment* ev,
  214.                                       const FW_CString& text,
  215.                                       ODCommandID commandID,
  216.                                       short afterItem,
  217.                                       FW_MenuKey menuKey)
  218. {
  219.     if (afterItem > CountItems(ev))
  220.         afterItem = CountItems(ev);
  221.     
  222.     short index = afterItem + 1;
  223.     
  224.     FW_CMenuItem* menuItem = FW_NEW(FW_CTextItem, (ev, this, index, text, commandID, menuKey));
  225.     this->AdoptMenuItemAfter(ev, menuItem, afterItem);
  226. }
  227.  
  228. //----------------------------------------------------------------------------------------
  229. //    FW_CPullDownMenu::InsertTextItemAfterCommand
  230. //----------------------------------------------------------------------------------------
  231.  
  232. void FW_CPullDownMenu::InsertTextItemAfterCommand(Environment* ev,
  233.                                                   const FW_CString& text,
  234.                                                   ODCommandID commandID,
  235.                                                   ODCommandID afterCommand,
  236.                                                   FW_MenuKey menuKey)
  237. {
  238.     FW_CMenuItem* item = this->PrivGetMenuItem(ev, afterCommand);
  239.     this->InsertTextItem(ev, text, commandID, item->GetIndex(ev), menuKey);
  240. }
  241.  
  242. //----------------------------------------------------------------------------------------
  243. //    FW_CPullDownMenu::AppendToggleItem
  244. //----------------------------------------------------------------------------------------
  245.  
  246. void FW_CPullDownMenu::AppendToggleItem(Environment* ev,
  247.                                         const FW_CString& trueText,
  248.                                         const FW_CString& falseText,
  249.                                         ODCommandID commandID,
  250.                                         FW_MenuKey menuKey)
  251. {
  252.     short index = CountItems(ev) + 1;
  253.     FW_CMenuItem* menuItem = FW_NEW(FW_CToggleItem, (ev, this, index, trueText, falseText, commandID, menuKey));
  254.     this->AdoptMenuItemLast(ev, menuItem);
  255. }
  256.  
  257. //----------------------------------------------------------------------------------------
  258. //    FW_CPullDownMenu::InsertToggleItem
  259. //----------------------------------------------------------------------------------------
  260.  
  261. void FW_CPullDownMenu::InsertToggleItem(Environment* ev,
  262.                                         const FW_CString& trueText,
  263.                                         const FW_CString& falseText,
  264.                                         ODCommandID commandID,
  265.                                         short afterItem,
  266.                                         FW_MenuKey menuKey)
  267. {
  268.     if (afterItem > CountItems(ev))
  269.         afterItem = CountItems(ev);
  270.     
  271.     short index = afterItem + 1;
  272.     
  273.     FW_CMenuItem* menuItem = FW_NEW(FW_CToggleItem, (ev, this, index, trueText, falseText, commandID, menuKey));
  274.     this->AdoptMenuItemAfter(ev, menuItem, afterItem);
  275. }
  276.  
  277. //----------------------------------------------------------------------------------------
  278. //    FW_CPullDownMenu::InsertToggleItemAfterCommand
  279. //----------------------------------------------------------------------------------------
  280.  
  281. void FW_CPullDownMenu::InsertToggleItemAfterCommand(Environment* ev,
  282.                                                     const FW_CString& trueText,
  283.                                                     const FW_CString& falseText,
  284.                                                     ODCommandID commandID,
  285.                                                     ODCommandID afterCommand,
  286.                                                     FW_MenuKey menuKey)
  287. {
  288.     FW_CMenuItem* item = this->PrivGetMenuItem(ev, afterCommand);
  289.     this->InsertToggleItem(ev, trueText, falseText, commandID, item->GetIndex(ev), menuKey);
  290. }
  291.  
  292. //----------------------------------------------------------------------------------------
  293. //    FW_CPullDownMenu::AppendSubMenu
  294. //----------------------------------------------------------------------------------------
  295.  
  296. void FW_CPullDownMenu::AppendSubMenu(Environment* ev,
  297.                                      FW_CPullDownMenu* adoptSubMenu)
  298. {
  299.     short index = CountItems(ev) + 1;
  300.     FW_CMenuItem* menuItem = FW_NEW(FW_CSubMenuItem, (ev, this, index, adoptSubMenu));
  301.     this->AdoptMenuItemLast(ev, menuItem);
  302. }
  303.  
  304. //----------------------------------------------------------------------------------------
  305. //    FW_CPullDownMenu::InsertSubMenu
  306. //----------------------------------------------------------------------------------------
  307.  
  308. void FW_CPullDownMenu::InsertSubMenu(Environment* ev,
  309.                                      FW_CPullDownMenu* adoptSubMenu,
  310.                                      short afterItem)
  311. {
  312.     if (afterItem > CountItems(ev))
  313.         afterItem = CountItems(ev);
  314.     
  315.     short index = afterItem + 1;
  316.     
  317.     FW_CMenuItem* menuItem = FW_NEW(FW_CSubMenuItem, (ev, this, index, adoptSubMenu));
  318.     this->AdoptMenuItemAfter(ev, menuItem, afterItem);
  319. }
  320.  
  321. //----------------------------------------------------------------------------------------
  322. //    FW_CPullDownMenu::InsertSubMenuAfterCommand
  323. //----------------------------------------------------------------------------------------
  324.  
  325. void FW_CPullDownMenu::InsertSubMenuAfterCommand(Environment* ev,
  326.                                                  FW_CPullDownMenu* adoptSubMenu,
  327.                                                  ODCommandID afterCommand)
  328. {
  329.     FW_CMenuItem* item = this->PrivGetMenuItem(ev, afterCommand);
  330.     this->InsertSubMenu(ev, adoptSubMenu, item->GetIndex(ev));
  331. }
  332.  
  333. //----------------------------------------------------------------------------------------
  334. //    FW_CPullDownMenu::AppendSeparator
  335. //----------------------------------------------------------------------------------------
  336.  
  337. void FW_CPullDownMenu::AppendSeparator(Environment* ev)
  338. {
  339.     short index = CountItems(ev) + 1;
  340.     FW_CMenuItem* menuItem = FW_NEW(FW_CSeparatorItem, (ev, this, index));
  341.     this->AdoptMenuItemLast(ev, menuItem);
  342. }
  343.  
  344. //----------------------------------------------------------------------------------------
  345. //    FW_CPullDownMenu::InsertSeparator
  346. //----------------------------------------------------------------------------------------
  347.  
  348. void FW_CPullDownMenu::InsertSeparator(Environment* ev,
  349.                                        short afterItem)
  350. {
  351.     if (afterItem > CountItems(ev))
  352.         afterItem = CountItems(ev);
  353.     
  354.     short index = afterItem + 1;
  355.     
  356.     FW_CMenuItem* menuItem = FW_NEW(FW_CSeparatorItem, (ev, this, index));
  357.     this->AdoptMenuItemAfter(ev, menuItem, afterItem);
  358. }
  359.  
  360. //----------------------------------------------------------------------------------------
  361. //    FW_CPullDownMenu::InsertSeparatorAfterCommand
  362. //----------------------------------------------------------------------------------------
  363.  
  364. void FW_CPullDownMenu::InsertSeparatorAfterCommand(Environment* ev,
  365.                                                    ODCommandID afterCommand)
  366. {
  367.     FW_CMenuItem* item = this->PrivGetMenuItem(ev, afterCommand);
  368.     this->InsertSeparator(ev, item->GetIndex(ev));
  369. }
  370.  
  371. //----------------------------------------------------------------------------------------
  372. //    FW_CPullDownMenu::RemoveItem
  373. //
  374. //  If an index greater than the number of items in the menu is specified,
  375. //    the last item is deleted.
  376. //----------------------------------------------------------------------------------------
  377.  
  378. void FW_CPullDownMenu::RemoveItem(Environment* ev, short position)
  379. {
  380.     FW_ASSERT(position > 0);
  381.     
  382.     if (position > CountItems(ev))
  383.         position = CountItems(ev);
  384.     
  385.     FW_TOrderedCollectionIterator<FW_CMenuItem> ite(fItems);    
  386.     FW_CMenuItem* itemToRemove = NULL;
  387.     
  388.     for (FW_CMenuItem* item = ite.First(); ite.IsNotComplete(); item = ite.Next())
  389.     {
  390.         short index = item->GetIndex(ev);
  391.         
  392.         if (index == position)
  393.             itemToRemove = item;
  394.         else if (index > position)
  395.         // if the current item is beneath the new item in the menu...
  396.         {
  397.             item->PrivSetIndex(ev, index - 1);
  398.             
  399. #ifdef FW_BUILD_MAC
  400.             if (fMenuBar != NULL)  // need to unregister and re-register the item
  401.             {
  402.                 fMenuBar->PrivMacUnregisterCommand(ev, item->GetCommandID(ev));
  403.                 fMenuBar->PrivMacRegisterCommand(ev, item->GetCommandID(ev), fMenuID, index - 1);
  404.             }
  405. #endif
  406.         }
  407.     }
  408.     
  409.     FW_ASSERT(itemToRemove);
  410.     fItems->Remove(itemToRemove);
  411.     
  412.     if (fMenuBar != NULL)
  413.         itemToRemove->PrivDetach(ev, fMenuBar);
  414.     
  415.     // now, actually delete the item
  416.     
  417. #ifdef FW_BUILD_MAC
  418.     DeleteMenuItem(fPlatformMenu, position);
  419. #endif
  420.  
  421. #ifdef FW_BUILD_WIN
  422.     DeleteMenu(fPlatformMenu.menu, position - 1, MF_BYPOSITION);
  423. #endif
  424.  
  425.     delete itemToRemove;
  426. }
  427.  
  428. //----------------------------------------------------------------------------------------
  429. //    FW_CPullDownMenu::AdoptMenuItemLast
  430. //----------------------------------------------------------------------------------------
  431.  
  432. void FW_CPullDownMenu::AdoptMenuItemLast(Environment* ev, FW_CMenuItem* menuItem)
  433. {
  434.     fItems->AddLast(menuItem);
  435.     
  436.     if (fMenuBar != NULL)
  437.         menuItem->PrivAttach(ev, fMenuBar);
  438. }
  439.  
  440. //----------------------------------------------------------------------------------------
  441. //    FW_CPullDownMenu::AdoptMenuItemAfter
  442. //----------------------------------------------------------------------------------------
  443. //  If afterItem is greater than the number of items in the menu, the item is added to
  444. //  then bottom of the menu; if it's zero, the item is added to the top.
  445.  
  446. void FW_CPullDownMenu::AdoptMenuItemAfter(Environment* ev, FW_CMenuItem* menuItem, short afterItem)
  447. {
  448.     FW_ASSERT(afterItem >= 0 && afterItem <= CountItems(ev));
  449.     
  450.     FW_TOrderedCollectionIterator<FW_CMenuItem> ite(fItems);    
  451.     FW_CMenuItem* prevItem = NULL;
  452.     
  453.     for (FW_CMenuItem* item = ite.First(); ite.IsNotComplete(); item = ite.Next())
  454.     {
  455.         short index = item->GetIndex(ev);
  456.         
  457.         if (index == afterItem)
  458.             prevItem = item;
  459.         else if (index > afterItem)
  460.         // if the current item is beneath the new item in the menu...
  461.         {
  462.             item->PrivSetIndex(ev, index + 1);  // adjust item numbers
  463.             
  464. #ifdef FW_BUILD_MAC    
  465.             if (fMenuBar != NULL)  // need to unregister and re-register the item
  466.             {
  467.                 fMenuBar->PrivMacUnregisterCommand(ev, item->GetCommandID(ev));
  468.                 fMenuBar->PrivMacRegisterCommand(ev, item->GetCommandID(ev), fMenuID, index + 1);
  469.             }
  470. #endif
  471.         }
  472.     }
  473.     
  474.     if (afterItem == 0)  // add the item to the menu
  475.         fItems->AddFirst(menuItem);
  476.     else
  477.     {
  478.         FW_ASSERT(prevItem);
  479.         fItems->AddAfter(prevItem, menuItem);
  480.     }
  481.     
  482.     if (fMenuBar != NULL)
  483.         menuItem->PrivAttach(ev, fMenuBar);
  484. }
  485.  
  486. //----------------------------------------------------------------------------------------
  487. //    FW_CPullDownMenu::GetCommandID
  488. //----------------------------------------------------------------------------------------
  489. //    returns FW_kNoCommand if not found or submenu, FW_kSeparatorCommand if separator
  490.  
  491. ODCommandID FW_CPullDownMenu::GetCommandID(Environment* ev, short position) const
  492. {
  493. #ifdef FW_BUILD_MAC
  494.     FW_TOrderedCollectionIterator<FW_CMenuItem> ite(fItems);
  495.     for (FW_CMenuItem* item = ite.First(); ite.IsNotComplete(); item = ite.Next())
  496.     {
  497.         if (item->GetIndex(ev) == position)
  498.             return item->GetCommandID(ev);
  499.     }
  500.         
  501.     return FW_kNoCommand;
  502. #endif
  503.  
  504. #ifdef FW_BUILD_WIN
  505.     return ::GetMenuItemID(fPlatformMenu.menu, position-1);    // zero-based on windows
  506. #endif
  507. }
  508.  
  509. //----------------------------------------------------------------------------------------
  510. //    FW_CPullDownMenu::PrivGetMenuItem
  511. //----------------------------------------------------------------------------------------
  512.  
  513. FW_CMenuItem* FW_CPullDownMenu::PrivGetMenuItem(Environment* ev, ODCommandID commandID) const
  514. {
  515.     FW_ASSERT(commandID != FW_kNoCommand);
  516.     FW_ASSERT(commandID != FW_kSeparatorCommand);
  517.     
  518.     FW_TOrderedCollectionIterator<FW_CMenuItem> ite(fItems);
  519.     for (FW_CMenuItem* item = ite.First(); ite.IsNotComplete(); item = ite.Next())
  520.     {
  521.         if (item->GetCommandID(ev) == commandID)
  522.             return item;
  523.         else 
  524.         {
  525.             FW_CMenuItem* subItem = item->PrivGetMenuItem(ev, commandID);
  526.             if (subItem != NULL)
  527.                 return subItem;
  528.         }
  529.             
  530.     }
  531.         
  532.     return NULL;
  533. }
  534.  
  535. //----------------------------------------------------------------------------------------
  536. //    FW_CPullDownMenu::PrivFindMenuWithID
  537. //----------------------------------------------------------------------------------------
  538.  
  539. FW_CPullDownMenu* FW_CPullDownMenu::PrivFindMenuWithID(Environment* ev, ODMenuID menuID) const
  540. {
  541.     FW_ASSERT(IsAttachedToMenuBar(ev)); // Otherwise it doesn't make sense because menuID 
  542.                                         // are only assigned when the menu is attached
  543.     
  544.     FW_TOrderedCollectionIterator<FW_CMenuItem> ite(fItems);
  545.     for (FW_CMenuItem* item = ite.First(); ite.IsNotComplete(); item = ite.Next())
  546.     {
  547.         FW_CPullDownMenu* subMenu = item->PrivFindMenuWithID(ev, menuID);
  548.         if (subMenu != NULL)
  549.             return subMenu;
  550.     }
  551.     
  552.     return NULL;
  553. }
  554.  
  555. //----------------------------------------------------------------------------------------
  556. //    FW_CPullDownMenu::DisableAll
  557. //----------------------------------------------------------------------------------------
  558.  
  559. void FW_CPullDownMenu::DisableAll(Environment* ev)
  560. {
  561. #ifdef FW_BUILD_MAC
  562.         // ----- On the Mac disable all the items at once
  563.         // [MEB] If enableFlags is set to 0, then menus with enabled items may be disabled.
  564.         // That's because DisableAll is called first, and then menu items are enabled one by one.
  565.         // When a menu item is enabled using FW_CMenuBar::EnableCommand et al, no check is made
  566.         // to make sure its menu is enabled as well.
  567.         (*fPlatformMenu)->enableFlags = 0x00000001;
  568. #endif
  569.  
  570.     FW_TOrderedCollectionIterator<FW_CMenuItem> ite(fItems);
  571.     for (FW_CMenuItem* item = ite.First(); ite.IsNotComplete(); item = ite.Next())
  572.     {
  573.         item->PrivDisableAll(ev);
  574.     }    
  575. }
  576.  
  577. //----------------------------------------------------------------------------------------
  578. //    FW_CPullDownMenu::EnableAll
  579. //----------------------------------------------------------------------------------------
  580.  
  581. void FW_CPullDownMenu::EnableAll(Environment* ev)
  582. {
  583. #ifdef FW_BUILD_MAC
  584.         // ----- On the Mac enable all the items at once
  585.         (*fPlatformMenu)->enableFlags = 0xFFFFFFFF;
  586. #endif
  587.  
  588.     FW_TOrderedCollectionIterator<FW_CMenuItem> ite(fItems);
  589.     for (FW_CMenuItem* item = ite.First(); ite.IsNotComplete(); item = ite.Next())
  590.     {
  591.         item->PrivEnableAll(ev);
  592.     }    
  593. }
  594.  
  595. //----------------------------------------------------------------------------------------
  596. //    FW_CPullDownMenu::PrivAcquireMenuID
  597. //----------------------------------------------------------------------------------------
  598.  
  599. ODMenuID FW_CPullDownMenu::PrivAcquireMenuID(Environment* ev, FW_CMenuBar* menuBar)
  600. {
  601.     FW_ASSERT(fMenuID == FW_kUnattachedMenuID);
  602.     fMenuID = menuBar->PrivGetNewMenuID(ev);
  603. #ifdef FW_BUILD_MAC    
  604.     (*fPlatformMenu)->menuID = fMenuID;
  605. #endif
  606.     return fMenuID;
  607. }
  608.  
  609. //----------------------------------------------------------------------------------------
  610. //    FW_CPullDownMenu::PrivRelinquishMenuID
  611. //----------------------------------------------------------------------------------------
  612.  
  613. void FW_CPullDownMenu::PrivRelinquishMenuID(Environment* ev)
  614. {
  615. FW_UNUSED(ev);
  616.     FW_ASSERT(fMenuID != FW_kUnattachedMenuID);
  617.     fMenuID = FW_kUnattachedMenuID;
  618. #ifdef FW_BUILD_MAC    
  619.     (*fPlatformMenu)->menuID = FW_kUnattachedMenuID;
  620. #endif
  621. }
  622.  
  623. //----------------------------------------------------------------------------------------
  624. //    FW_CPullDownMenu::PrivAttach
  625. //----------------------------------------------------------------------------------------
  626.  
  627. void FW_CPullDownMenu::PrivAttach(Environment* ev, FW_CMenuBar* menuBar)
  628. {
  629.     FW_ASSERT(fMenuBar == NULL);
  630.     fMenuBar = menuBar;
  631.     
  632.     FW_TOrderedCollectionIterator<FW_CMenuItem> ite(fItems);
  633.     for (FW_CMenuItem* item = ite.First(); ite.IsNotComplete(); item = ite.Next())
  634.     {
  635.         item->PrivAttach(ev, menuBar);
  636.     }
  637. }
  638.  
  639. //----------------------------------------------------------------------------------------
  640. //    FW_CPullDownMenu::PrivDetach
  641. //----------------------------------------------------------------------------------------
  642.  
  643. void FW_CPullDownMenu::PrivDetach(Environment* ev, FW_CMenuBar* menuBar)
  644. {    
  645.     FW_ASSERT(fMenuBar == menuBar);
  646.     fMenuBar = NULL;
  647.     
  648.     FW_TOrderedCollectionIterator<FW_CMenuItem> ite(fItems);
  649.     for (FW_CMenuItem* item = ite.First(); ite.IsNotComplete(); item = ite.Next())
  650.     {
  651.         item->PrivDetach(ev, menuBar);
  652.     }
  653. }
  654.  
  655. //----------------------------------------------------------------------------------------
  656. //    FW_CPullDownMenu::PrivAttachedToMenuBar
  657. //----------------------------------------------------------------------------------------
  658.  
  659. void FW_CPullDownMenu::PrivAttachedToMenuBar(Environment* ev, ODPart* part, FW_CMenuBar* menuBar, ODMenuID beforeID)
  660. {
  661.     FW_ASSERT(menuBar != NULL);
  662.     FW_ASSERT(fMenuBar == NULL);
  663.     FW_ASSERT(fMenuID == FW_kUnattachedMenuID);
  664.     
  665.     PrivAcquireMenuID(ev, menuBar);
  666.  
  667.     FW_CAcquiredODMenuBar aqODMenuBar = menuBar->AcquireODMenuBar(ev);
  668.     
  669.     if (beforeID == -1)
  670.     {
  671. #ifdef FW_BUILD_WIN
  672.         // [WIN_PORT]: AddMenuLast takes an ODPlatformMenu* in OD/Win -- different from OD/Mac
  673.         aqODMenuBar->AddMenuLast(ev, fMenuID, &fPlatformMenu, part);
  674. #else
  675.         aqODMenuBar->AddMenuLast(ev, fMenuID, fPlatformMenu, part);
  676. #endif
  677.     }
  678.     else
  679.     {
  680. #ifdef FW_BUILD_WIN
  681.         // [WIN_PORT]: AddMenuBefore takes an ODPlatformMenu* in OD/Win -- different from OD/Mac
  682.         aqODMenuBar->AddMenuBefore(ev, fMenuID, &fPlatformMenu, part, beforeID);
  683. #else
  684.         aqODMenuBar->AddMenuBefore(ev, fMenuID, fPlatformMenu, part, beforeID);
  685. #endif
  686.     }
  687.     
  688.     PrivAttach(ev, menuBar);
  689. }
  690.  
  691. //----------------------------------------------------------------------------------------
  692. //    FW_CPullDownMenu::PrivDetachedFromMenuBar
  693. //----------------------------------------------------------------------------------------
  694.  
  695. void FW_CPullDownMenu::PrivDetachedFromMenuBar(Environment* ev, FW_CMenuBar* menuBar)
  696. {
  697. FW_UNUSED(menuBar);
  698.     FW_ASSERT(fMenuBar != NULL);
  699.     FW_ASSERT(fMenuBar == menuBar);
  700.     
  701.     fMenuBar->PrivRemoveMenu(ev, fMenuID);
  702.     
  703.     PrivDetach(ev, fMenuBar);
  704.     
  705.     PrivRelinquishMenuID(ev);
  706. }
  707.  
  708. //----------------------------------------------------------------------------------------
  709. //    FW_CPullDownMenu::Flatten
  710. //----------------------------------------------------------------------------------------
  711.  
  712. void FW_CPullDownMenu::Flatten(Environment* ev, FW_CWritableStream& stream) const
  713. {
  714.     //----- Save menu data -----
  715.     FW_CString menuTitle;
  716.     short count = CountItems(ev);
  717.  
  718. #ifdef FW_BUILD_MAC
  719.     menuTitle.ReplaceAll((*fPlatformMenu)->menuData);
  720.     FW_ASSERT(count == ::CountMItems(fPlatformMenu));
  721. #endif
  722. #ifdef FW_BUILD_WIN
  723.     menuTitle = fPlatformMenu.strMenu;
  724.     FW_ASSERT(count == ::GetMenuItemCount(fPlatformMenu.menu));
  725. #endif
  726.  
  727.     stream << menuTitle;
  728.     stream << count;
  729.     
  730.     //----- Save menu items -----
  731.     FW_TOrderedCollectionIterator<FW_CMenuItem> itemIter(fItems);
  732.     for (FW_CMenuItem* menuItem = itemIter.First(); itemIter.IsNotComplete(); menuItem = itemIter.Next())
  733.     {
  734.         FW_WRITE_DYNAMIC_OBJECT(stream, menuItem, FW_CMenuItem);
  735.     }
  736. }
  737.